package com.ls.fw.web.core.server.jetty;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;

/**
 * jetty嵌入服务
 * 
 * @author lisheng
 * @date 2016年3月13日 下午3:31:12
 * @version V1.0
 */
public class CustomJettyServer extends Server {
	private String xmlConfigPath;

	private String contextPath = "/";

	private String warPath;

	private int sslPort = 8443;
	private int port = 80;

	private String webAppDir = "src/main/webapp";

	private String webXmlPath = "src/main/webapp/WEB-INF/web.xml";

	private WebAppContext webapp;

	private String storePath;
	private String password;
	//org.apache.coyote.http11.Http11NioProtocol
	private String protocol = "http/1.1";
	public CustomJettyServer() {
		super();
	}

	public CustomJettyServer( String contextPath, int port) {
		super();
		this.port = port;
		this.contextPath = contextPath;
	}

	public String getXmlConfigPath() {
		return this.xmlConfigPath;
	}

	public CustomJettyServer setXmlConfigPath(String xmlConfigPath) {
		this.xmlConfigPath = xmlConfigPath;
		return this;
	}

	public String getContextPath() {
		return this.contextPath;
	}

	public CustomJettyServer setContextPath(String contextPath) {
		this.contextPath = contextPath;
		return this;
	}

	public String getWarPath() {
		return this.warPath;
	}

	public CustomJettyServer setWarPath(String warPath) {
		this.warPath = warPath;
		return this;
	}

	public int getPort() {
		return this.port;
	}

	public CustomJettyServer setPort(int port) {
		this.port = port;
		return this;
	}

	public String getWebAppDir() {
		return this.webAppDir;
	}

	public CustomJettyServer setWebAppDir(String webAppDir) {
		this.webAppDir = webAppDir;
		return this;
	}

	public String getWebXmlPath() {
		return this.webXmlPath;
	}

	public CustomJettyServer setWebXmlPath(String webXmlPath) {
		this.webXmlPath = webXmlPath;
		return this;
	}

	public WebAppContext getWebapp() {
		return this.webapp;
	}

	public CustomJettyServer setWebapp(WebAppContext webapp) {
		this.webapp = webapp;
		return this;
	}

	@Override
	protected void doStart() throws Exception {
		if (StringUtils.isNotBlank(warPath)) {
             applyHandle(true);
         } else {
             applyHandle(false);
         }
		super.doStart();
	}

	
	/**
	 * 启动服务
	 * @author lisheng
	 * @date 2016年3月13日 下午3:53:50
	 * @version V1.0
	 * @throws Exception
	 */
	public void startServer(){
		try {
			this.start();
			this.join();
		} catch (Exception e1) {
			e1.printStackTrace();
			System.exit(-1);
		}
	}

	protected void applyHandle(Boolean warDeployFlag) {
		  // 设置Jetty日志
        System.setProperty("org.eclipse.jetty.util.log.class", StdErrLog.class.getName());
        ServerConnector connector=new ServerConnector(this);
        connector.setPort(port);
        this.addConnector(connector);
        
        if(StringUtils.isNotBlank(storePath)
        		&& StringUtils.isNotBlank(password)){
	        HttpConfiguration https_config = new HttpConfiguration();
	        https_config.setSecureScheme("https");
	        https_config.setSecurePort(sslPort);
	        https_config.setOutputBufferSize(32768);
	        https_config.addCustomizer(new SecureRequestCustomizer());
	         
	        SslContextFactory sslContextFactory = new SslContextFactory();
	        sslContextFactory.setKeyStorePath(this.storePath);
	        sslContextFactory.setKeyStorePassword(this.password);
	        sslContextFactory.setKeyManagerPassword(password);
	        sslContextFactory.setIncludeProtocols("SSLv2", "SSLv3", "TLSv1");
	         
	        ServerConnector httpsConnector = new ServerConnector(this,
	                new SslConnectionFactory(sslContextFactory,protocol),
	                new HttpConnectionFactory(https_config));
	        httpsConnector.setPort(sslPort);
	        httpsConnector.setIdleTimeout(500000);
	        this.addConnector(httpsConnector);
        }
		ContextHandlerCollection handler = new ContextHandlerCollection();
		 // 设置在JVM退出时关闭Jetty的钩子。
        this.setStopAtShutdown(true);
		webapp = new WebAppContext();
		webapp.setContextPath(contextPath);
		// webapp.setDefaultsDescriptor("./jetty/etc/webdefault.xml");
		webapp.setParentLoaderPriority(true);
		if (!warDeployFlag) {
			webapp.setResourceBase(webAppDir);
			if (StringUtils.isNotBlank(webXmlPath)) {
				webapp.setDescriptor(webXmlPath);
			}
		} else {
			webapp.setWar(warPath);
		}
		webapp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed",
				"false");
		webapp.setInitParameter(
				"org.eclipse.jetty.servlet.Default.useFileMappedBuffer",
				"false"); 
		// webApp.setInitParams(Collections.singletonMap("org.mortbay.jetty.servlet.Default.useFileMappedBuffer", "false"));

		handler.addHandler(webapp);

		super.setHandler(handler);
	}
	public static void main(String[] args) throws Exception {
		CustomJettyServer jetty = new CustomJettyServer("/test", 80 );
//			jetty.setStorePath("D:\\server\\tomcat\\ssl\\lisheng.keystore");
//			jetty.setPassword("lisheng");
		jetty.startServer();
	}

	public String getStorePath() {
		return storePath;
	}

	public CustomJettyServer setStorePath(String storePath) {
		this.storePath = storePath;
		return this;
	}

	public int getSslPort() {
		return this.sslPort;
	}

	public CustomJettyServer setSslPort(int sslPort) {
		this.sslPort = sslPort;
		return this;
	}

	public String getPassword() {
		return password;
	}

	public CustomJettyServer setPassword(String password) {
		this.password = password;
		return this;
	}

	public String getProtocol() {
		return protocol;
	}

	public CustomJettyServer setProtocol(String protocol) {
		this.protocol = protocol;
		return this;
	}

	@Override
	public void join() throws InterruptedException {
		Thread t = new Thread(new Runnable() {
			
			@Override
			public void run() {
				System.out.println("[HINT] Hit Enter to reload the application quickly");
				try {
					// 等待用户输入回车重载应用.
					while (true) {
					    char c = (char) System.in.read();
					    if (c == '\n') {
					        JettyFactory.reloadContext(CustomJettyServer.this);
					        System.out.println("[HINT] Hit Enter to reload the application quickly");
					     }
					}
				} catch (Exception e) {
					e.printStackTrace();
					System.exit(-1);
				}
			}
		});
		t.setDaemon(true);
		t.start();
		super.join();
		System.out.println(this.getURI()); 
	}
}